<template>
  <div class="form-select" ref="selectRef">
    <div class="tx-btn text-blue-dark mb-1">{{ title }}</div>
    <div
      class="form-select__select"
      :class="{
        'is-active': isListOpen,
        'has-error': myError.length > 0 && !optional
      }"
      @click="isListOpen = !isListOpen"
    >
      <input
        type="text"
        class="form-select__btn"
        :placeholder="optionPlaceholder"
        v-model="myValue"
        readonly
      />
      <div class="form-select__menu">
        <ScrollBar>
          <ul class="form-select__list">
            <li
              class="form-select__option"
              v-for="item in options"
              :key="item.key"
              @click="selectOption(item.value)"
            >
              {{ item.name }}
            </li>
          </ul>
        </ScrollBar>
      </div>
    </div>
    <div v-show="!optional" class="input-error">
      此为必填项
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
import ScrollBar from '@/common/ScrollBar/index.vue';

const props = defineProps({
  options: { type: Array, default: () => [] },
  value: { type: String, default: '' },
  title: { type: String, default: '' },
  optionPlaceholder: { type: String, default: '请选择' },
  error: { type: Object, default: null },
  isEmptyFirst: { type: Boolean, default: false },
  optional: { type: Boolean, default: false },
  componentKey: { type: String, default: null }
});

const emit = defineEmits(['updateValue', 'updateError']);

const timestamp = ref(Date.now());
const isListOpen = ref(false);
const myError = ref([]);
const selectRef = ref(null);

const myValue = computed({
  get() {
    return props.options.some((v) => v.value == props.value) ? props.value : '';
  },
  set(nVal) {
    emit('updateValue', nVal);
    checkError();
  }
});

function closeList() {
  isListOpen.value = false;
}

function checkError() {
  if (props.optional) return;
  const isValid = myValue.value;
  const key = props.componentKey ?? 'tempKey';
  const idx = myError.value.indexOf(key);
  if (!isValid && idx < 0) myError.value.push(key);
  if (isValid && idx > -1) myError.value.splice(idx, 1);
  emit('updateError', { key: props.componentKey, isPass: Boolean(isValid) });
}

function selectOption(val) {
  myValue.value = val;
  isListOpen.value = false;
}

// 点击外部关闭下拉菜单
function handleClickOutside(event) {
  if (selectRef.value && !selectRef.value.contains(event.target)) {
    isListOpen.value = false;
  }
}

onMounted(() => {
  if (!myValue.value && !props.isEmptyFirst && props.options && props.options[0]) {
    emit('updateValue', props.options[0].value);
    checkError();
  }

  // 添加全局点击事件监听
  document.addEventListener('click', handleClickOutside);
});

onBeforeUnmount(() => {
  // 移除全局点击事件监听
  document.removeEventListener('click', handleClickOutside);
});
</script>

<style lang="scss" scoped>
.tx-body-p {
  font-size: 16px;
  font-weight: 400;
  line-height: 1.75
}

@media(max-width: 1023.98px) {
  .tx-body-p {
      font-size:14px;
      line-height: 1.714;
      letter-spacing: .01em
  }
}

.tx-body {
  font-size: 16px;
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: .01em
}

@media(max-width: 1023.98px) {
  .tx-body {
      font-size:14px;
      line-height: 1.285;
      letter-spacing: .01em
  }
}

.tx-btn {
  font-size: 14px;
  font-weight: 500;
  line-height: 1.285;
  letter-spacing: .04em
}

@media(max-width: 1023.98px) {
  .tx-btn {
      line-height:1.428
  }
}

@media(max-width: 767.98px) {
  .tx-btn {
      line-height:1.285
  }
}

.text-blue-dark {
  --bs-text-opacity: 1;
  color: rgba(0,50,160,var(--bs-text-opacity))!important;
}

.mb-1 {
  margin-bottom: 4px!important
}

.form-select {
  margin-bottom: 36px;
}

@media (max-width: 767.98px) {
  .form-select {
    margin-bottom: 24px;
  }
}

.form-select__select {
  position: relative;
}

.form-select__select::after {
  content: '';
  position: absolute;
  right: 12px;
  top: 50%;
  width: 16px;
  height: 16px;
  background: url("~static/images/icons/icon-tab-arrow.svg") center center no-repeat;
  background-size: 100% auto;
  transform: translateY(-50%) rotateZ(90deg);
  transition: transform .3s ease-in-out;
  cursor: pointer;
}

.form-select__btn {
  @extend .tx-body-p;
  color: #1A1C20;
  background: #F7F7FA;
  border-radius: 4px;
  border: none;
  padding: 8px 12px;
  outline: none;
  width: 100%;
  min-width: 240px;
  cursor: pointer;
}

@media (max-width: 767.98px) {
  .form-select__btn {
    background: rgba(255,255,255,1);
  }
}

.form-select__btn::placeholder {
  @extend .tx-body-p;
  color: #C0C0C4;
}

.form-select__menu {
  position: absolute;
  width: 100%;
  z-index: 3;
  left: 0;
  top: 48px;
  opacity: 0;
  border-radius: 4px;
  overflow: hidden;
  pointer-events: none;
  background: #F7F7FA;
  transform: translateY(-20px);
  transition: transform .3s ease-in-out, opacity .3s ease-in-out;
}

@media (max-width: 767.98px) {
  .form-select__menu {
    background: rgba(255,255,255,1);
  }
}

.form-select__menu > .scroll-bar ::v-deep .simple-bar {
  max-height: 144px;
}

.form-select__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.form-select__option {
  padding: 12px;
  @extend .tx-body;
  color: #000;
  cursor: pointer;
}

.form-select__option:not(:first-child) {
  border-top: 1px solid rgba(255,255,255,1);
}

@media (max-width: 767.98px) {
  .form-select__option:not(:first-child) {
    border-top: 1px solid #F7F7FA;
  }
}

/* active state */
.form-select__select.is-active .form-select__menu {
  transform: translateY(0);
  opacity: 1;
  pointer-events: visible;
}

/* error state */
.form-select__select.has-error .form-select__btn {
  padding: 6px 10px;
  border: 2px solid #FF0044;
}

.form-select__select.has-error + .input-error {
  opacity: 1;
  position: relative;
}

.input-error {
  position: absolute;
  margin-top: 12px;
  color: #CE031A;
  opacity: 0;
  transition: opacity .15s ease-in-out;
  pointer-events: none;
}
</style>